#!/usr/bin/env node

/**
 * Vosk模型下载脚本
 * 用于下载语音识别所需的模型文件
 */

import fs from 'fs'
import path from 'path'
import https from 'https'
import { execSync } from 'child_process'
import { fileURLToPath } from 'url'

// 获取当前文件的目录
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

// 模型配置
const MODELS = {
  'vosk-model-small-cn-0.22': {
    url: 'https://alphacephei.com/vosk/models/vosk-model-small-cn-0.22.zip',
    size: '42MB',
    description: '中文小模型 (0.22版本)',
  },
  'vosk-model-cn-0.22': {
    url: 'https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip',
    size: '1.2GB',
    description: '中文标准模型 (0.22版本)',
  },
}

// 下载目录
const DOWNLOAD_DIR = path.join(__dirname, '..', 'src-bex', 'assets', 'models')

/**
 * 确保目录存在
 * @param {string} dir - 目录路径
 */
function ensureDir(dir) {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true })
    console.log(`创建目录: ${dir}`)
  }
}

/**
 * 下载文件
 * @param {string} url - 下载URL
 * @param {string} destPath - 目标路径
 * @returns {Promise<void>}
 */
function downloadFile(url, destPath) {
  return new Promise((resolve, reject) => {
    console.log(`开始下载: ${url}`)
    console.log(`目标路径: ${destPath}`)

    const file = fs.createWriteStream(destPath)

    https
      .get(url, (response) => {
        if (response.statusCode !== 200) {
          reject(new Error(`下载失败，状态码: ${response.statusCode}`))
          return
        }

        const totalSize = parseInt(response.headers['content-length'], 10)
        let downloadedSize = 0
        let lastProgress = 0

        response.on('data', (chunk) => {
          downloadedSize += chunk.length
          const progress = Math.round((downloadedSize / totalSize) * 100)

          if (progress > lastProgress + 9) {
            console.log(`下载进度: ${progress}%`)
            lastProgress = progress
          }
        })

        response.pipe(file)

        file.on('finish', () => {
          file.close()
          console.log('下载完成')
          resolve()
        })

        file.on('error', (err) => {
          fs.unlink(destPath, () => {}) // 删除不完整的文件
          reject(err)
        })
      })
      .on('error', (err) => {
        reject(err)
      })
  })
}

/**
 * 解压ZIP文件
 * @param {string} zipPath - ZIP文件路径
 * @param {string} extractDir - 解压目录
 */
function extractZip(zipPath, extractDir) {
  try {
    console.log(`解压文件: ${zipPath}`)

    // 检查是否有unzip命令
    try {
      execSync('unzip -v', { stdio: 'ignore' })
      execSync(`unzip -o "${zipPath}" -d "${extractDir}"`, { stdio: 'inherit' })
    } catch {
      // 如果没有unzip命令，尝试使用其他方法
      console.log('未找到unzip命令，尝试使用Node.js解压...')
      // 这里可以添加Node.js解压逻辑
      throw new Error('请安装unzip命令或手动解压文件')
    }

    console.log('解压完成')
  } catch (error) {
    console.error('解压失败:', error.message)
    throw error
  }
}

/**
 * 下载并安装模型
 * @param {string} modelName - 模型名称
 */
async function downloadModel(modelName) {
  const modelConfig = MODELS[modelName]
  if (!modelConfig) {
    throw new Error(`未知模型: ${modelName}`)
  }

  console.log(`\n开始下载模型: ${modelName}`)
  console.log(`描述: ${modelConfig.description}`)
  console.log(`大小: ${modelConfig.size}`)

  // 确保下载目录存在
  ensureDir(DOWNLOAD_DIR)

  const zipPath = path.join(DOWNLOAD_DIR, `${modelName}.zip`)
  const modelDir = path.join(DOWNLOAD_DIR, modelName)

  try {
    // 检查模型是否已存在
    if (fs.existsSync(modelDir)) {
      console.log(`模型已存在: ${modelDir}`)
      return
    }

    // 下载模型文件
    await downloadFile(modelConfig.url, zipPath)

    // 解压模型文件
    extractZip(zipPath, DOWNLOAD_DIR)

    // 删除ZIP文件
    fs.unlinkSync(zipPath)
    console.log(`已删除ZIP文件: ${zipPath}`)

    console.log(`模型安装完成: ${modelDir}`)
  } catch (error) {
    console.error(`模型下载失败: ${error.message}`)

    // 清理不完整的文件
    if (fs.existsSync(zipPath)) {
      fs.unlinkSync(zipPath)
    }

    throw error
  }
}

/**
 * 列出可用模型
 */
function listModels() {
  console.log('\n可用模型:')
  Object.entries(MODELS).forEach(([name, config]) => {
    console.log(`  ${name}: ${config.description} (${config.size})`)
  })
}

/**
 * 主函数
 */
async function main() {
  const args = process.argv.slice(2)
  const command = args[0]

  try {
    switch (command) {
      case 'list':
        listModels()
        break

      case 'download': {
        const modelName = args[1]
        if (!modelName) {
          console.error('请指定要下载的模型名称')
          console.log('使用方法: node download-vosk-models.js download <model-name>')
          console.log('或使用: node download-vosk-models.js download all')
          process.exit(1)
        }

        if (modelName === 'all') {
          for (const name of Object.keys(MODELS)) {
            await downloadModel(name)
          }
        } else {
          await downloadModel(modelName)
        }
        break
      }

      case 'clean':
        if (fs.existsSync(DOWNLOAD_DIR)) {
          fs.rmSync(DOWNLOAD_DIR, { recursive: true, force: true })
          console.log(`已清理下载目录: ${DOWNLOAD_DIR}`)
        } else {
          console.log('下载目录不存在')
        }
        break

      default:
        console.log('Vosk模型下载工具')
        console.log('\n使用方法:')
        console.log('  node download-vosk-models.js list                    # 列出可用模型')
        console.log('  node download-vosk-models.js download <model-name>   # 下载指定模型')
        console.log('  node download-vosk-models.js download all            # 下载所有模型')
        console.log('  node download-vosk-models.js clean                   # 清理下载目录')
        console.log('\n示例:')
        console.log('  node download-vosk-models.js download vosk-model-small-cn-0.22')
        break
    }
  } catch (error) {
    console.error('操作失败:', error.message)
    process.exit(1)
  }
}

// 运行主函数
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  main()
}
